package com.wry.juc;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <h1>  </h1>
 *
 * @author wry
 * @since 2025.04.02
 */
@Slf4j
public class MyLock {

    public static void main(String[] args) {



        ReentrantLock lock = new ReentrantLock();
        lock.lock();
        lock.unlock();

        MyLock lock1 = new MyLock();
        for (int i = 0; i < 10; i++) {
            CompletableFuture.runAsync(() -> {
                lock1.lock();
                lock1.lock();
                lock1.lock();
                System.out.println(Thread.currentThread().getName()+"-执行任务..");
                try { Thread.sleep(500L); } catch (InterruptedException e) { e.printStackTrace();}
                lock1.unLock();
                lock1.unLock();
                lock1.unLock();
                System.out.println(Thread.currentThread().getName()+"-执行任务完成");
            });
        }

        try { Thread.sleep(100000L); } catch (InterruptedException e) { e.printStackTrace();}
    }

    private AtomicInteger state = new AtomicInteger(0);

    // 头节点
    private AtomicReference<Node> head = new AtomicReference<>(new Node());

    // 尾节点
    private AtomicReference<Node> tail = new AtomicReference<>(head.get());

    private Thread lockThread;

    public void lock() {

        if (state.get() == 0){
            // CAS加锁
            if (state.compareAndSet(0, 1)) {
                lockThread = Thread.currentThread();
                log.info("{}-加锁成功success", lockThread.getName());
                return;
            }
        } else {
            if (lockThread == Thread.currentThread()) {
                // 重入
                int increment = state.incrementAndGet();
                log.info("{}-重入锁成功,加锁次数={}", lockThread.getName(), increment);
                return;
            }
        }

        // 加锁失败
        Node currentNode = new Node();
        currentNode.thread = Thread.currentThread();
        // CAS+自旋尝试加入尾节点
        while (true) {
            // 当前尾节点
            Node currentTail = tail.get();
            // 将当前加锁失败的节点置为尾节点
            if (tail.compareAndSet(currentTail, currentNode)) {
                log.info("{}-加锁失败，添加到尾节点成功", currentNode.thread.getName());
                currentNode.prev = currentTail;
                currentTail.next = currentNode;
                break;
            }
        }

        while (true){
            // 唤醒之后的线程，尝试CAS
            if (currentNode.prev == head.get() && state.compareAndSet(0, 1)) {
                lockThread = Thread.currentThread();
                // 将当前节点置为头节点
                head.set(currentNode);
                currentNode.prev.next = null;
                currentNode.prev = null;
                log.info( "{}-被唤醒之后，拿到锁",Thread.currentThread().getName());
                return;
            }
            // 阻塞
            LockSupport.park();
        }

    }

    public void unLock() {
        if (lockThread != Thread.currentThread()) {
            throw new RuntimeException(Thread.currentThread() + "-当前线程未持有锁!unlock失败！");
        }
        // 重入次数
        int count = state.get();
        if (count > 1) {
            state.set(count -1);
            log.info("{}-解锁成功，重入次数还剩={}", Thread.currentThread().getName(), state.get());
            return;
        }
        // 解锁
        Node headNode = head.get();
        Node nextNode = headNode.next;
        lockThread = null;
        state.set(0);
        if (nextNode != null){
            log.info("{} 唤醒 {}", Thread.currentThread().getName() ,nextNode.thread.getName());
            LockSupport.unpark(nextNode.thread);
        }
    }

    class Node {
        Node prev;
        Node next;
        Thread thread;
    }
}
